package com.zx.wx.utils;

import com.alibaba.fastjson.JSON;
import com.zx.wx.wxInterface.Base;
import com.zx.wx.wxInterface.Request;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.sql.Timestamp;
import java.util.Arrays;
import java.util.Formatter;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.UUID;


public class BaseUtils
{
    private static Logger logger = LogManager.getLogger(BaseUtils.class);
    

    public static Map<String, String> getConfig(String appid,String appsecret,String url,Base base,Request Request)
    {
    	String jsapi_ticket = getApi_ticket(appid, appsecret,base,Request);
        Map<String, String> ret = new HashMap<String, String>();
        String nonceStr = UUID.randomUUID().toString().replaceAll("-", "");
        String timestamp = Long.toString(System.currentTimeMillis() / 1000);
        String string1;
        String signature = "";
        
        // 注意这里参数名必须全部小写，且必须有序
        string1 = "jsapi_ticket=" + jsapi_ticket + "&noncestr=" + nonceStr + "&timestamp=" + timestamp + "&url=" + url;
        try
        {
            MessageDigest crypt = MessageDigest.getInstance("SHA-1");
            crypt.reset();
            crypt.update(string1.getBytes("UTF-8"));
            
            Formatter formatter = new Formatter();
            for (byte b : crypt.digest())
            {
                formatter.format("%02x", b);
            }
            signature = formatter.toString();
            formatter.close();
        }
        catch (NoSuchAlgorithmException e)
        {
            e.printStackTrace();
        }
        catch (UnsupportedEncodingException e)
        {
            e.printStackTrace();
        }
        
        ret.put("url", url);
        ret.put("jsapi_ticket", jsapi_ticket);
        ret.put("nonceStr", nonceStr);
        ret.put("timestamp", timestamp);
        ret.put("signature", signature);
        ret.put("string1",string1);
        return ret;
    }
    
    
    public static synchronized String getApi_ticket(String appid, String appsecret,Base base,Request Request)
    {
//        String access_token=getAccess_token(appid, appsecret, base, Request);
        Map<String,Object> ramResult=base.getRamApi_ticket(appid, appsecret);
		//利用短点机制，判断值,任意一项出错，则有误
		if(
			ramResult==null||ramResult.size()==0||
			ramResult.get("api_ticket") == null || ("".equals(ramResult.get("api_ticket")))||
			ramResult.get("api_ticket_update_time")==null || ("".equals(ramResult.get("api_ticket_update_time"))) || !checkTime(Long.valueOf(ramResult.get("api_ticket_update_time").toString()))
		  )
		{
			Map<String,Object> dbResult=base.getDBApi_ticket(appid, appsecret);
			//找数据库,任何因素有误，则判断失败
			if(dbResult==null||
				   dbResult.get("value") == null || ("".equals(dbResult.get("value")))||
				   ("".equals(dbResult.get("update_time")))||
				   !checkTime(Timestamp.valueOf(dbResult.get("update_time").toString()).getTime())
			  )
			{
				Map<String,Object> wxResult=getwxApi_ticket(getAccess_token(appid, appsecret, base, Request), Request);
				if(dbResult==null){//查看数据库是否存在，存在，则更新。不存在，则增加。
					base.setDBApi_ticket(wxResult.get("ticket").toString(), appid, appsecret);
				}
				else
				{
					base.updateDBApi_ticket(wxResult.get("ticket").toString(), appid, appsecret);
				}
				base.setRamApi_ticket(wxResult.get("ticket").toString(),String.valueOf(System.currentTimeMillis()), appid, appsecret);
				return wxResult.get("ticket").toString();
			}
			else
			{
				//1,将access_token和update_time（毫秒）写入缓存
				base.setRamApi_ticket(dbResult.get("value").toString(),String.valueOf(System.currentTimeMillis()), appid, appsecret);
				return dbResult.get("value").toString();
			}
		}
		else 
		{
			
			//1,校验缓存中的access_token时间，正确则返回
			return ramResult.get("api_ticket").toString();
		}
    }
    
    @SuppressWarnings("unchecked")
	public static Map<String,Object> getwxApi_ticket(String access_token,Request Request){
    	//数据库没有，走下面流程
    	String url="https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+access_token+"&type=jsapi";
        String resultJson = Request.doGet(url);// 从微信服务器获取值
        Map<String, Object> resultMap=null;
        try
        {
            resultMap = JSON.parseObject(resultJson, Map.class);
        }
        catch (Exception e)
        {
            logger.error("getwxApi_ticket:"+e.getMessage());
        }
        if (resultMap.get("errcode").equals("0"))
        {
            logger.info("获取getwxApi_ticket失败：" + resultJson);
        }
    	return resultMap;
    }
    
    /**
	 *2016年7月17日 下午2:06:42
	 *@param appid
	 *@param appsecret
	 *@return
	 *@note:从所有服务器获取access_token
	 */
	public static synchronized String getAccess_token(String appid,String appsecret,Base base,Request Request){
		Map<String,Object> ramResult=base.getRamAccess_token(appid, appsecret);
		//利用短点机制，判断值,任意一项出错，则有误
		if(
			ramResult==null||ramResult.size()==0||
			ramResult.get("access_token") == null || ("".equals(ramResult.get("access_token")))||
			ramResult.get("access_token_update_time")==null || ("".equals(ramResult.get("access_token_update_time"))) || !checkTime(Long.valueOf(ramResult.get("access_token_update_time").toString()))
		  )
		{
			Map<String,Object> dbResult=base.getDBAccess_token(appid, appsecret);
			//找数据库,任何因素有误，则判断失败
			if(dbResult==null||
				   dbResult.get("value") == null || ("".equals(dbResult.get("value")))||
				   ("".equals(dbResult.get("update_time")))||
				   !checkTime(Timestamp.valueOf(dbResult.get("update_time").toString()).getTime())
			  )
			{
				Map<String,Object> wxResult=getwxAccess_token(appid, appsecret, Request);
				if(dbResult==null){//查看数据库是否存在，存在，则更新。不存在，则增加。
					base.setDBAccess_token(wxResult.get("access_token").toString(), appid, appsecret);
				}
				else
				{
					base.updateDBAccess_token(wxResult.get("access_token").toString(), appid, appsecret);
				}
				base.setRamAccess_token(wxResult.get("access_token").toString(),String.valueOf(System.currentTimeMillis()), appid, appsecret);
				return wxResult.get("access_token").toString();
			}
			else
			{
				//1,将access_token和update_time（毫秒）写入缓存
				base.setRamAccess_token(dbResult.get("value").toString(),String.valueOf(System.currentTimeMillis()), appid, appsecret);
				return dbResult.get("value").toString();
			}
		}
		else 
		{
			
			//1,校验缓存中的access_token时间，正确则返回
			return ramResult.get("access_token").toString();
		}
	}
	
    public static boolean checkTime(long time){
		long  sysTime=System.currentTimeMillis();
		long  wxbaseNum=(7200-200)*1000;//微信基数,防止超时，砍掉200秒
//      //去内存取
      if((sysTime>=time&&sysTime<time+wxbaseNum)){   //获取时间-----------当前时间--------------结束时间
           return true;
      }
      else
      {
    	  return false;
      }
		
    }
    
    
	@SuppressWarnings("unchecked")
	public static Map<String,Object> getwxAccess_token(String appid, String appsecret,Request Request){
    	//数据库没有，走下面流程
        String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+appid+"&secret="+appsecret;
        String resultJson = Request.doGet(url);// 从微信服务器获取值
        Map<String, Object> resultMap=null;
        try
        {
            resultMap = JSON.parseObject(resultJson, Map.class);
        }
        catch (Exception e)
        {
            logger.error("getwxAccess_token:"+e.getMessage());
        }
        if (resultMap.get("errcode") != null)
        {
            logger.info("获取wxAccess_token失败：" + resultJson);
        }
    	return resultMap;
    }
    
    // userid兑换openid，
    public static String openidToUserid(String access_token, String openid,Request Request)
    {
        String url = "https://qyapi.weixin.qq.com/cgi-bin/user/convert_to_userid?access_token=" + access_token;
        String data = "{\"openid\": \"" + openid + "\"}";
        String result = Request.doPost(url, data);
        return result;
    }
    
    /**
     * 2016年7月12日 下午2:06:42
     * 
     * @param access_token
     * @return
     * @note:获取所有微信服务器ip
     */
    public static List<String> getIp_list(String access_token,Request Request)
    {
        String url = "https://api.weixin.qq.com/cgi-bin/getcallbackip?access_token=" + access_token;
        String result = Request.doGet(url);
        result = result.replaceAll("\"", "").replaceAll("\\{", "").replaceAll("\\}", "").split(":")[1].replace("[", "")
            .replace("]", "");
        String[] list = result.split(",");
        return Arrays.asList(list);
    }
    
    @SuppressWarnings("finally")
    public static Map<String, String> xmlToMap(String xml)
    {
        // String content =
        // "<xml><URL><![CDATA[http://211.149.202.130/cms/wx]]></URL><ToUserName><![CDATA[okYfGv9twGuc-_i1aiJ4lgi5_REc]]></ToUserName><FromUserName><![CDATA[okYfGv9nc-kNIuJjNgb-VGHh1n3o]]></FromUserName><CreateTime>2016</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[sadfaasdfsfgsdgdgsfafsfafsfsafsf]]></Content><MsgId>111</MsgId></xml>";
        Document document = null;
        Map<String, String> resultMap = new HashMap<>();
        try
        {
            document = DocumentHelper.parseText(xml);
            Element root = document.getRootElement();
            for (Iterator<?> it = root.elementIterator(); it.hasNext();)
            {
                Element element = (Element)it.next();
                resultMap.put(element.getName(), element.getText());
            }
        }
        catch (DocumentException e)
        {
            logger.error("xmlToMap:" + e.getMessage());
        }
        finally
        {
            return resultMap;
        }
        
    }
}
